package com.hzw.saas.web.app.user.controller;


import com.alibaba.fastjson.JSON;
import com.hzw.saas.api.user.IUserAccountService;
import com.hzw.saas.api.user.IUserProfileService;
import com.hzw.saas.api.user.bo.UserAccountBO;
import com.hzw.saas.api.user.bo.UserProfileBO;
import com.hzw.saas.common.config.annotation.SysLog;
import com.hzw.saas.common.config.util.AssertUtil;
import com.hzw.saas.common.security.pojo.dto.SaasUser;
import com.hzw.saas.common.security.utils.SecurityUtils;
import com.hzw.saas.common.util.IdWorker;
import com.hzw.saas.web.app.user.dto.UserProfileInfo;
import com.hzw.saas.web.app.user.param.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiOperationSort;
import jodd.util.StringUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import ma.glasnost.orika.MapperFacade;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.*;

/**
 * <p>
 * 用户配置表 前端控制器
 * </p>
 *
 * @author sonam
 * @since 2020-12-21
 */
@RestController
@RequestMapping("/user")
@RequiredArgsConstructor
@Api(tags = "用户中心/用户资料")
@Slf4j
public class UserProfileController {

    private final IUserProfileService userProfileService;
    private final IUserAccountService userAccountService;
    private final IdWorker idWorker;
    private final MapperFacade mapperFacade;

    @GetMapping("/profile")
    @SysLog
    @ApiOperation(value = "获取用户详细信息", notes = "获取该登录用户的详细信息")
    @ApiOperationSort(-1)
    public ResponseEntity<UserProfileInfo> get() {
        SaasUser saasUser = SecurityUtils.getUser();
        UserProfileBO userProfileBO = userProfileService.get(saasUser.getUserId());
        if (userProfileBO == null) {
            return ResponseEntity.ok(null);
        }
        UserAccountBO account = userAccountService.getAccount(saasUser.getUserId());
        UserProfileInfo userProfileInfo = new UserProfileInfo()
            .setEmail(account.getEmail())
            .setRealName(userProfileBO.getRealName())
            .setAvatar(userProfileBO.getAvatar())
            .setTitle(userProfileBO.getTitle())
            .setOrgan(userProfileBO.getOrgan())
            .setResearch(userProfileBO.getResearch())
            .setIntroduce(userProfileBO.getIntroduce())
            .setTreatise(userProfileBO.getTreatise())
            .setBook(userProfileBO.getBook())
            .setAwards(mapperFacade.mapAsList(conver(AwardsParam.class, userProfileBO.getAwards()), AwardsParam.class))
            .setCertificates(mapperFacade.mapAsList(conver(CertificateParam.class, userProfileBO.getCertificate()), CertificateParam.class))
            .setEducations(mapperFacade.mapAsList(conver(EducationParam.class, userProfileBO.getEducation()), EducationParam.class))
            .setExperiences(mapperFacade.mapAsList(conver(ExperienceParam.class, userProfileBO.getExperience()), ExperienceParam.class))
            .setPatents1(new ArrayList<>())
            .setPatents2(new ArrayList<>())
            .setPatents3(new ArrayList<>());
        List<PatentParam> patentParams = mapperFacade.mapAsList(conver(PatentParam.class, userProfileBO.getPatent()), PatentParam.class);
        patentParams.forEach(patentParam -> {
            // 类型: 1论文成果 | 2学术著作 | 3发明专利
            Integer type = patentParam.getType() == null ? 1 : patentParam.getType();
            switch (type) {
                case 2:
                    userProfileInfo.getPatents2().add(patentParam);
                    break;
                case 3:
                    userProfileInfo.getPatents3().add(patentParam);
                    break;
                default:
                    // 默认：论文成果
                    patentParam.setType(1);
                    userProfileInfo.getPatents1().add(patentParam);
                    break;
            }
        });
        return ResponseEntity.ok(userProfileInfo);
    }

    @PutMapping("/profile")
    @SysLog(operation = "编辑资料", mode = 3)
    @ApiOperation(value = "编辑资料")
    @ApiOperationSort(0)
    public ResponseEntity<Boolean> updateProfile(@Validated @RequestBody UserProfileParam userProfileParam) {
        SaasUser saasUser = SecurityUtils.getUser();
        UserProfileBO userProfileBO = mapperFacade.map(userProfileParam, UserProfileBO.class);
        userProfileBO.setUserId(saasUser.getUserId());
        userProfileService.update(userProfileBO);
        return ResponseEntity.ok(true);
    }

    @PostMapping("/awards")
    @SysLog(operation = "添加荣誉证书", mode = 3)
    @ApiOperation(value = "添加荣誉证书")
    @ApiOperationSort(1)
    public ResponseEntity<Void> addAward(@RequestBody @Validated AwardsParam awardsParam) {
        doAdd(awardsParam);
        return ResponseEntity.ok().build();
    }

    @PutMapping("/awards")
    @SysLog(operation = "编辑荣誉证书", mode = 3)
    @ApiOperation(value = "编辑荣誉证书")
    @ApiOperationSort(6)
    public ResponseEntity<Void> updateAward(@RequestBody @Validated AwardsParam awardsParam) {
        doUpdate(awardsParam);
        return ResponseEntity.ok().build();
    }

    @DeleteMapping("/awards/{id}")
    @SysLog(operation = "删除荣誉证书", mode = 3)
    @ApiOperation(value = "删除荣誉证书")
    @ApiOperationSort(11)
    public ResponseEntity<Void> deleteAwards(@PathVariable String id) {
        doDelete(new AwardsParam().setId(id));
        return ResponseEntity.ok().build();
    }

    @GetMapping("/awards/{id}")
    @SysLog
    @ApiOperation(value = "获取荣誉证书")
    @ApiOperationSort(16)
    public ResponseEntity<AwardsParam> getAwardsInfo(@PathVariable String id) {
        UserProfileBO userProfileBO = userProfileService.get(SecurityUtils.getUser().getUserId());
        String awards = userProfileBO.getAwards();
        return ResponseEntity.ok(getT(awards, id, AwardsParam.class));
    }

    @PostMapping("/certificate")
    @SysLog(operation = "添加证书", mode = 3)
    @ApiOperation(value = "添加证书")
    @ApiOperationSort(2)
    public ResponseEntity<Void> addCertificate(@RequestBody @Validated CertificateParam certificateParam) {
        doAdd(certificateParam);
        return ResponseEntity.ok().build();
    }

    @PutMapping("/certificate")
    @SysLog(operation = "编辑证书", mode = 3)
    @ApiOperation(value = "编辑证书")
    @ApiOperationSort(7)
    public ResponseEntity<Void> updateCertificate(@RequestBody @Validated CertificateParam certificateParam) {
        doUpdate(certificateParam);
        return ResponseEntity.ok().build();
    }

    @DeleteMapping("/certificate/{id}")
    @SysLog(operation = "删除证书", mode = 3)
    @ApiOperation(value = "删除证书")
    @ApiOperationSort(12)
    public ResponseEntity<Void> deleteCertificate(@PathVariable String id) {
        doDelete(new CertificateParam().setId(id));
        return ResponseEntity.ok().build();
    }

    @GetMapping("/certificate/{id}")
    @SysLog
    @ApiOperation(value = "获取证书")
    @ApiOperationSort(17)
    public ResponseEntity<CertificateParam> getCertificateInfo(@PathVariable String id) {
        UserProfileBO userProfileBO = userProfileService.get(SecurityUtils.getUser().getUserId());
        String certificate = userProfileBO.getCertificate();
        return ResponseEntity.ok(getT(certificate, id, CertificateParam.class));
    }

    @PostMapping("/education")
    @SysLog(operation = "添加教育经历", mode = 3)
    @ApiOperation(value = "添加教育经历")
    @ApiOperationSort(3)
    public ResponseEntity<Void> addEducation(@RequestBody @Validated EducationParam educationParam) {
        doAdd(educationParam);
        return ResponseEntity.ok().build();
    }

    @PutMapping("/education")
    @SysLog(operation = "编辑教育经历", mode = 3)
    @ApiOperation(value = "编辑教育经历")
    @ApiOperationSort(8)
    public ResponseEntity<Void> updateEducation(@RequestBody @Validated EducationParam educationParam) {
        doUpdate(educationParam);
        return ResponseEntity.ok().build();
    }

    @DeleteMapping("/education/{id}")
    @SysLog(operation = "删除教育经历", mode = 3)
    @ApiOperation(value = "删除教育经历")
    @ApiOperationSort(13)
    public ResponseEntity<Void> deleteEducation(@PathVariable String id) {
        doDelete(new EducationParam().setId(id));
        return ResponseEntity.ok().build();
    }

    @GetMapping("/education/{id}")
    @SysLog
    @ApiOperation(value = "获取教育经历")
    @ApiOperationSort(18)
    public ResponseEntity<EducationParam> getEducationInfo(@PathVariable String id) {
        UserProfileBO userProfileBO = userProfileService.get(SecurityUtils.getUser().getUserId());
        String education = userProfileBO.getEducation();
        return ResponseEntity.ok(getT(education, id, EducationParam.class));
    }

    @PostMapping("/experience")
    @SysLog(operation = "添加工作经历", mode = 3)
    @ApiOperation(value = "添加工作经历")
    @ApiOperationSort(4)
    public ResponseEntity<Void> addExperience(@RequestBody @Validated ExperienceParam experienceParam) {
        doAdd(experienceParam);
        return ResponseEntity.ok().build();
    }

    @PutMapping("/experience")
    @SysLog(operation = "编辑工作经历", mode = 3)
    @ApiOperation(value = "编辑工作经历")
    @ApiOperationSort(9)
    public ResponseEntity<Void> updateExperience(@RequestBody @Validated ExperienceParam experienceParam) {
        doUpdate(experienceParam);
        return ResponseEntity.ok().build();
    }

    @DeleteMapping("/experience/{id}")
    @SysLog(operation = "删除工作经历", mode = 3)
    @ApiOperation(value = "删除工作经历")
    @ApiOperationSort(14)
    public ResponseEntity<Void> deleteExperience(@PathVariable String id) {
        doDelete(new ExperienceParam().setId(id));
        return ResponseEntity.ok().build();
    }

    @GetMapping("/experience/{id}")
    @SysLog
    @ApiOperation(value = "获取工作经历")
    @ApiOperationSort(19)
    public ResponseEntity<ExperienceParam> getExperienceInfo(@PathVariable String id) {
        UserProfileBO userProfileBO = userProfileService.get(SecurityUtils.getUser().getUserId());
        String experience = userProfileBO.getExperience();
        return ResponseEntity.ok(getT(experience, id, ExperienceParam.class));
    }

    @PostMapping("/patent")
    @SysLog(operation = "添加论文成果/学术著作/发明专利", mode = 3)
    @ApiOperation(value = "添加论文成果/学术著作/发明专利")
    @ApiOperationSort(5)
    public ResponseEntity<Void> addProfess(@RequestBody @Validated PatentParam patentParam) {
        doAdd(patentParam);
        return ResponseEntity.ok().build();
    }

    @PutMapping("/patent")
    @SysLog(operation = "编辑论文成果/学术著作/发明专利", mode = 3)
    @ApiOperation(value = "编辑论文成果/学术著作/发明专利")
    @ApiOperationSort(10)
    public ResponseEntity<Void> updateProfess(@RequestBody @Validated PatentParam patentParam) {
        doUpdate(patentParam);
        return ResponseEntity.ok().build();
    }

    @DeleteMapping("/patent/{id}")
    @SysLog(operation = "删除论文成果/学术著作/发明专利", mode = 3)
    @ApiOperation(value = "删除论文成果/学术著作/发明专利")
    @ApiOperationSort(15)
    public ResponseEntity<Void> deletePatent(@PathVariable String id) {
        doDelete(new PatentParam().setId(id));
        return ResponseEntity.ok().build();
    }

    @GetMapping("/patent/{id}")
    @SysLog
    @ApiOperation(value = "获取论文成果/学术著作/发明专利")
    @ApiOperationSort(20)
    public ResponseEntity<PatentParam> getPatentInfo(@PathVariable String id) {
        UserProfileBO userProfileBO = userProfileService.get(SecurityUtils.getUser().getUserId());
        String patent = userProfileBO.getPatent();
        PatentParam patentParam = getT(patent, id, PatentParam.class);
        if(Objects.isNull(patentParam.getType())) {
            patentParam.setType(1);
        }
        return ResponseEntity.ok(patentParam);
    }

    private <T extends IdParam> T getT(String content, String id, Class<T> cls) {
        List<IdParam> idParams = conver(cls, content);
        for (IdParam idParam : idParams) {
            if (Objects.equals(idParam.getId(), id)) {
                return mapperFacade.map(idParam, cls);
            }
        }
        return null;
    }

    private void doAdd(IdParam idParam) {
        String userId = SecurityUtils.getUser().getUserId();
        String id = String.valueOf(idWorker.nextId());
        idParam.setId(id);
        idParam.setCreateTime(new Date());
        String content;
        UserProfileBO userProfileBO = userProfileService.get(userId);

        UserProfileBO userProfileQuery = new UserProfileBO().setUserId(userId);
        if (idParam instanceof AwardsParam) {
            content = addToContent(idParam, userProfileBO.getAwards());
            userProfileQuery.setAwards(content);
        }

        if (idParam instanceof CertificateParam) {
            content = addToContent(idParam, userProfileBO.getCertificate());
            userProfileQuery.setCertificate(content);
        }

        if (idParam instanceof EducationParam) {
            content = addToContent(idParam, userProfileBO.getEducation());
            userProfileQuery.setEducation(content);
        }

        if (idParam instanceof ExperienceParam) {
            content = addToContent(idParam, userProfileBO.getExperience());
            userProfileQuery.setExperience(content);
        }

        if (idParam instanceof PatentParam) {
            content = addToContent(idParam, userProfileBO.getPatent());
            userProfileQuery.setPatent(content);
        }

        userProfileService.update(userProfileQuery);
    }

    private String addToContent(IdParam idParam, String oldContent) {
        List<IdParam> idParams = new ArrayList<>();
        try {
            if (StringUtil.isNotBlank(oldContent)) {
                idParams = conver(idParam.getClass(), oldContent);
            }
        } catch (Exception e) {
            // ignore
            e.printStackTrace();
        }
        idParams.add(idParam);
        return JSON.toJSONString(idParams);
    }

    private void doUpdate(IdParam idParam) {
        String id = idParam.getId();
        idParam.setUpdateTime(new Date());
        AssertUtil.assertThrow("操作失败,ID不能为空", Objects.isNull(id));
        UserProfileBO userProfileBO = userProfileService.get(SecurityUtils.getUser().getUserId());
        String content = "";

        UserProfileBO userProfileQuery = new UserProfileBO().setUserId(SecurityUtils.getUser().getUserId());
        if (idParam instanceof AwardsParam) {
            content = updateToContent(idParam, userProfileBO.getAwards());
            userProfileQuery.setAwards(content);
        }

        if (idParam instanceof CertificateParam) {
            content = updateToContent(idParam, userProfileBO.getCertificate());
            userProfileQuery.setCertificate(content);
        }

        if (idParam instanceof EducationParam) {
            content = updateToContent(idParam, userProfileBO.getEducation());
            userProfileQuery.setEducation(content);
        }

        if (idParam instanceof ExperienceParam) {
            content = updateToContent(idParam, userProfileBO.getExperience());
            userProfileQuery.setExperience(content);
        }

        if (idParam instanceof PatentParam) {
            content = updateToContent(idParam, userProfileBO.getPatent());
            userProfileQuery.setPatent(content);
        }

        AssertUtil.assertThrow("操作失败,ID不存在", Objects.isNull(content));
        userProfileService.update(userProfileQuery);
    }

    private String updateToContent(IdParam idParam, String oldContent) {
        try {
            String id = idParam.getId();
            List<IdParam> idParams = conver(idParam.getClass(), oldContent);

            boolean flag = false;
            for (int i = 0; i < idParams.size(); i++) {
                if (Objects.equals(idParams.get(i).getId(), id)) {
                    idParam.setCreateTime(idParams.get(i).getCreateTime());
                    idParams.set(i, idParam);
                    flag = true;
                }
            }

            if (flag) return JSON.toJSONString(idParams);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    private List<IdParam> conver(Class<? extends IdParam> cls, String content) {
        List<IdParam> idParams = new ArrayList<>();
        try {
            idParams.addAll(JSON.parseArray(content, cls));
        } catch (Exception e) {
        }
        return idParams;
    }

    private void doDelete(IdParam idParam) {
        UserProfileBO userProfileBO = userProfileService.get(SecurityUtils.getUser().getUserId());
        String content = "";

        UserProfileBO userProfileQuery = new UserProfileBO().setUserId(SecurityUtils.getUser().getUserId());
        if (idParam instanceof AwardsParam) {
            content = deleteToContent(idParam, userProfileBO.getAwards());
            userProfileQuery.setAwards(content);
        }

        if (idParam instanceof CertificateParam) {
            content = deleteToContent(idParam, userProfileBO.getCertificate());
            userProfileQuery.setCertificate(content);
        }

        if (idParam instanceof EducationParam) {
            content = deleteToContent(idParam, userProfileBO.getEducation());
            userProfileQuery.setEducation(content);
        }

        if (idParam instanceof ExperienceParam) {
            content = deleteToContent(idParam, userProfileBO.getExperience());
            userProfileQuery.setExperience(content);
        }

        if (idParam instanceof PatentParam) {
            content = deleteToContent(idParam, userProfileBO.getPatent());
            userProfileQuery.setPatent(content);
        }

        AssertUtil.assertThrow("操作失败,ID不存在", Objects.isNull(content));
        userProfileService.update(userProfileQuery);
    }

    private String deleteToContent(IdParam idParam, String oldContent) {
        try {
            String id = idParam.getId();
            List<IdParam> idParams = conver(idParam.getClass(), oldContent);

            Iterator<IdParam> iterator = idParams.iterator();
            boolean flag = false;
            while (iterator.hasNext()) {
                IdParam next = iterator.next();
                if (Objects.equals(next.getId(), id)) {
                    iterator.remove();
                    flag = true;
                }
            }

            if (flag) return JSON.toJSONString(idParams);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }


}
